<!DOCTYPE html>
<html lang="zh-CH">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Game</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      button {
        border: none;
        outline: none;
        cursor: pointer;
        user-select: none;
      }

      .btn {
        box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
      }

      .btn:active {
        filter: brightness(0.8);
        transition: filter 0.3s;
      }

      .hide {
        display: none !important;
      }

      .container {
        display: flex;
        flex-direction: column;
        margin: 60px auto 0;
        padding: 20px;
        width: 60vw;
        height: auto;
        background-color: #eee;
      }

      .count-down {
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 20px;
      }

      .count-down span {
        display: inline-block;
        color: red;
        font-size: 26px;
        font-weight: 700;
      }
      .row.game-space {
        display: flex;
        justify-content: space-around;
        align-items: center;
      }

      .point {
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
        padding: 40px 0;
        width: 180px;
        height: 240px;
        background-color: #fff;
      }

      .people {
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 8px;
        width: 20px;
        height: 20px;
        background-color: #ccc;
        color: #fff;
        cursor: pointer;
        user-select: none;
        border-radius: 4px;
      }

      .actions {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: 90px;
      }

      .actions button {
        padding: 4px 14px;
        background-color: #fff;
        border-radius: 4px;
        font-size: 22px;
      }

      .restart {
        display: flex;
        justify-content: center;
        margin: 40px 0;
      }

      .restart button {
        padding: 8px 18px;
        background-color: #66bb6a;
        color: #fff;
        border-radius: 4px;
      }

      .active {
        background-color: #f00;
      }

      .game-introduction {
        display: flex;
        flex-direction: column;
      }
      .game-introduction p {
        margin-top: 8px;
        color: #555;
        line-height: 1.5em;
        font-size: 13px;
      }

      @media screen and (max-width: 768px) {
        .container {
          width: 90vw;
        }
        .point {
          width: 120px;
        }
      }

      .animation-zoom {
        animation: zoom 1s;
        animation-iteration-count: 1;
        animation-fill-mode: both; // Fix Firefox from firing animations only once
      }

      @keyframes zoom {
        0% {
          transform: scale(0.2);
          opacity: 1;
        }

        70% {
          transform: scale(2);
        }

        100% {
          transform: scale(1);
          opacity: 0;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="row count-down">
        <div>剩余时间 <span></span> ⏱</div>
      </div>
      <div class="row game-space">
        <div class="point point-birth"></div>
        <div class="actions">
          <button class="jump-to-end btn">⇨</button>
          <button class="jump-to-birth btn">⇦</button>
        </div>
        <div class="point point-end"></div>
      </div>
      <div class="row restart">
        <button class="btn">重新开始</button>
      </div>
      <div class="row game-introduction hide">
        <h3>🚩游戏攻略</h3>
        <p>
          一座桥，同时只能两个人过桥，他们共用一个手电筒。现有五个人，每个人的过桥时间都不一样，分别为：1、3、6、8、12。怎样让他们用最短的时间过去？
        </p>
      </div>
    </div>

    <script>
      let peopleBirth = [1, 3, 6, 8, 12]
      let peopleEnd = []
      let peopleHavaLighting = [1, 3, 6, 8, 12]
      let countDown = 30
      let gameOverCount = 0

      const arrayMaxItem = (arr) => Math.max(...arr)

      // 数组差集
      const arrayDiff = (a, b) => {
        return a.filter(function (v) {
          return b.indexOf(v) == -1
        })
      }

      const arraryIncludeArraryItem = (a, b) => {
        for (let i = 0; i < b.length; i++) {
          if (a.indexOf(b[i]) < 0) return false
        }
        return true
      }

      const activePeople = () => {
        $(".point .people")
          .off("click")
          .on("click", function () {
            if ($(this).siblings(".active").length > 1) {
              alert("⛵船太小，最多乘坐两人")
              return
            }
            if ($(this).parent().hasClass("point-birth")) {
              $(".point-end .people").removeClass("active")
            }
            if ($(this).parent().hasClass("point-end")) {
              $(".point-birth .people").removeClass("active")
            }
            $(this).toggleClass("active")
          })
      }

      const movePeopleToEnd = () => {
        const template = `
            <div class='people'></div>
          `
        $(".point-end").append()
      }

      const showGameIntroduction = () => {
        $(".game-introduction").removeClass("hide")
      }

      const gameOver = () => {
        alert("⏱时间不够喽，游戏结束！")
        restart()
        gameOverCount += 1
        if (gameOverCount === 1) showGameIntroduction()
      }

      const gameBeat = () => {
        alert("🎉恭喜通关！")
        restart()
      }

      const jumpToEndListener = () => {
        $(".jump-to-end").click(function () {
          const active = $(".point-birth .people.active")

          if (active.length === 0) {
            alert("⛵没有人乘船")
            return
          }

          if (
            active.length === 1 &&
            countDown > parseInt(active[0].innerHTML)
          ) {
            alert("🤣带个小伙伴再过桥吧")
            return
          }

          let currentActives = []

          active.each(function (index, item) {
            const value = parseInt(item.innerHTML)
            peopleEnd.push(value)
            currentActives.push(value)
          })

          if (arraryIncludeArraryItem(peopleBirth, peopleHavaLighting)) {
            peopleHavaLighting = peopleEnd

            countDown -= arrayMaxItem(currentActives)
            counterRender()

            pointRender(peopleEnd, "end")

            peopleBirth = arrayDiff(peopleBirth, peopleEnd)
            pointRender(peopleBirth, "birth")

            if (peopleBirth.length === 0) gameBeat()
          } else {
            alert("💡没有灯，危险！")
          }
        })
      }

      const jumpToBirthListener = () => {
        $(".jump-to-birth").click(function () {
          const active = $(".point-end .people.active")

          if (active.length === 0) {
            alert("⛵没有人乘船")
            return
          }

          if (
            active.length === 2 &&
            countDown > parseInt(active[0].innerHTML)
          ) {
            alert("🍭一个人回去可以节约时间哦")
            return
          }

          let currentActives = []

          active.each(function (index, item) {
            const value = parseInt(item.innerHTML)
            peopleBirth.push(value)
            currentActives.push(value)
          })

          if (arraryIncludeArraryItem(peopleEnd, peopleHavaLighting)) {
            peopleHavaLighting = peopleBirth

            countDown -= arrayMaxItem(currentActives)
            counterRender()

            pointRender(peopleBirth, "birth")

            peopleEnd = arrayDiff(peopleEnd, peopleBirth)
            pointRender(peopleEnd, "end")

            if (peopleBirth.length === 0) gameBeat()
          } else {
            alert("💡没有灯，危险！")
          }
        })
      }

      const restart = () => {
        peopleBirth = [1, 3, 6, 8, 12]
        peopleEnd = []
        peopleHavaLighting = []
        countDown = 30

        counterRender()
        pointRender(peopleBirth, "birth")
        pointRender(peopleEnd, "end")
      }

      const restartListener = () => $(".restart").click(restart)

      const pointRender = (peopleArray, point = "birth") => {
        const $point = point === "birth" ? $(".point-birth") : $(".point-end")
        $point.empty()
        peopleArray.forEach((item) => {
          const template = `<div class="people btn">${item}</div>`
          $point.append(template)
        })
        activePeople()
      }

      const counterRender = () => {
        if (parseInt(countDown) < 0) {
          gameOver()
          return
        }
        const $span = $(".count-down span").text(countDown)
        $span.addClass("animation-zoom")
        setTimeout(() => {
          $span.removeClass("animation-zoom")
        }, 1000)
      }

      counterRender()
      pointRender(peopleBirth, "birth")
      jumpToEndListener()
      jumpToBirthListener()
      restartListener()
    </script>
  </body>
</html>
